package com.eudon.genius.api.core.parser.component;

import com.eudon.genius.api.core.dto.ApiInfo;
import com.eudon.genius.api.core.dto.AppInfo;
import com.eudon.genius.api.core.dto.GroupInfo;
import com.eudon.genius.api.core.dto.PropertiesDto;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.MethodDeclaration;
import com.github.javaparser.ast.type.Type;
import com.github.javaparser.resolution.types.ResolvedType;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * API信息构建器
 * 负责协调各个解析器组件，构建完整的API文档结构
 *
 * @author eudon
 * @since 2025/9/25
 */
@Slf4j
public class ApiInfoBuilder {
    private final PropertiesDto propertiesDto;
    private final JavaDocParser javaDocParser;
    private final AnnotationParser annotationParser;
    private final ParameterParser parameterParser;
    @Getter
    private final TypeResolver typeResolver;

    /**
     * RESTful方法注解
     */
    private static final Set<String> REST_METHOD_ANNOTATIONS;

    static {
        Set<String> annotations = new HashSet<>();
        annotations.add("GetMapping");
        annotations.add("PostMapping");
        annotations.add("PutMapping");
        annotations.add("DeleteMapping");
        annotations.add("PatchMapping");
        annotations.add("RequestMapping");
        REST_METHOD_ANNOTATIONS = Collections.unmodifiableSet(annotations);
    }

    public ApiInfoBuilder(PropertiesDto propertiesDto, JavaDocParser javaDocParser,
                          AnnotationParser annotationParser,
                          ParameterParser parameterParser,
                          TypeResolver typeResolver) {
        this.propertiesDto = propertiesDto;
        this.javaDocParser = javaDocParser;
        this.annotationParser = annotationParser;
        this.parameterParser = parameterParser;
        this.typeResolver = typeResolver;
    }

    /**
     * 构建应用信息
     *
     * @param compilationUnits 编译单元列表
     * @return 应用信息
     */
    public AppInfo buildAppInfo(List<CompilationUnit> compilationUnits) {
        log.info("开始构建API文档，处理 {} 个编译单元", compilationUnits.size());
        AppInfo appInfo = new AppInfo();
        appInfo.setAppName(propertiesDto.getAppName());

        List<GroupInfo> groups = new ArrayList<>();

        for (CompilationUnit compilationUnit : compilationUnits) {
            try {
                List<GroupInfo> unitGroups = buildGroupsFromCompilationUnit(compilationUnit);
                groups.addAll(unitGroups);
            } catch (Exception e) {
                log.error("处理编译单元时发生错误", e);
            }
        }

        appInfo.setGroups(groups);

        log.info("API文档构建完成，共 {} 个分组，{} 个接口",
                groups.size(),
                groups.stream().mapToInt(g -> g.getApiInfos().size()).sum());

        return appInfo;
    }

    /**
     * 从编译单元构建分组信息
     */
    private List<GroupInfo> buildGroupsFromCompilationUnit(CompilationUnit compilationUnit) {
        List<GroupInfo> groups = new ArrayList<>();

        List<ClassOrInterfaceDeclaration> all = compilationUnit.findAll(ClassOrInterfaceDeclaration.class);
        ClassOrInterfaceDeclaration declaration = all.get(0);
        try {
            GroupInfo group = buildGroup(compilationUnit, declaration);
            if (group != null && !group.getApiInfos().isEmpty()) {
                groups.add(group);
            }
        } catch (Exception e) {
            log.error("处理Controller类 {} 时发生错误", declaration.getNameAsString(), e);
        }


        return groups;
    }

    /**
     * 从Controller类构建分组信息
     */
    private GroupInfo buildGroup(CompilationUnit compilationUnit,
                                 ClassOrInterfaceDeclaration clazz) {

        GroupInfo group = new GroupInfo();

        // 解析类文档信息
        JavaDocParser.ClassDocInfo classDocInfo = javaDocParser.parseClassDoc(clazz);
        group.setGroupName(classDocInfo.getClassName());
        group.setGroupDesc(classDocInfo.getDescription());
        group.setSince(classDocInfo.getSince());
        group.setVersion(classDocInfo.getVersion());

        // 解析类级别的@RequestMapping
        String classBaseUrl = annotationParser.parseClassRequestMapping(clazz);

        // 解析所有RESTful方法
        List<ApiInfo> apiInfos = new ArrayList<>();

        for (MethodDeclaration method : clazz.getMethods()) {
            if (isRestfulMethod(method)) {
                try {
                    ApiInfo apiInfo = buildApiInfoFromMethod(
                            compilationUnit, clazz, method, classBaseUrl);
                    if (apiInfo != null) {
                        apiInfos.add(apiInfo);
                    }
                } catch (Exception e) {
                    log.error("处理方法 {} 时发生错误", method.getNameAsString(), e);
                }
            }
        }

        group.setApiInfos(apiInfos);

        log.debug("构建分组: {}, 包含 {} 个接口", group.getGroupName(), apiInfos.size());

        return group;
    }

    /**
     * 从方法构建API信息
     */
    private ApiInfo buildApiInfoFromMethod(CompilationUnit compilationUnit,
                                           ClassOrInterfaceDeclaration controllerClass,
                                           MethodDeclaration method,
                                           String classBaseUrl) {

        ApiInfo apiInfo = new ApiInfo();

        // 设置基本信息
        apiInfo.setApiName(method.getNameAsString());

        // 解析方法文档信息
        JavaDocParser.MethodDocInfo methodDocInfo = javaDocParser.parseMethodDoc(method);
        apiInfo.setApiName(methodDocInfo.getMethodName());
        apiInfo.setApiDesc(methodDocInfo.getDescription());

        // 解析方法映射信息
        AnnotationParser.MethodMappingInfo mappingInfo = annotationParser.parseMethodMapping(method);
        if (mappingInfo == null) {
            return null;
        }
        apiInfo.setHttpMethod(mappingInfo.getHttpMethod());

        // 构建完整URL
        String fullUrl = buildFullUrl(classBaseUrl, mappingInfo.getUrl());
        apiInfo.setApiUrl(fullUrl);

        // 解析方法参数
        List<ApiInfo.Parameter> parameters = parameterParser.parseMethodParameters(method, methodDocInfo);
        apiInfo.setParameters(parameters);

        // 解析返回值
        ApiInfo.Return returnInfo = buildReturnInfo(method, methodDocInfo);
        apiInfo.set_return(returnInfo);

        log.debug("构建API: {} {} {}", apiInfo.getHttpMethod(), apiInfo.getApiUrl(), apiInfo.getApiName());

        return apiInfo;
    }

    /**
     * 构建返回值信息
     */
    private ApiInfo.Return buildReturnInfo(MethodDeclaration method,
                                           JavaDocParser.MethodDocInfo methodDocInfo) {

        ApiInfo.Return returnInfo = new ApiInfo.Return();

        // 获取返回类型
        Type returnType = method.getType();
        String typeName = returnType.asString();

        returnInfo.setReturnName("result");
        returnInfo.setReturnDesc(methodDocInfo.getReturnDescription() != null ?
                methodDocInfo.getReturnDescription() : "返回结果");
        returnInfo.setReturnType(typeName);
        returnInfo.setSimpleTypeName(getSimpleTypeName(typeName));
        returnInfo.setIsPrimitive(typeResolver.isPrimitiveType(typeName));

        // 解析复杂返回类型的字段
        if (!Boolean.TRUE.equals(returnInfo.getIsPrimitive()) && !"void".equals(typeName)) {
            try {
                ResolvedType resolvedReturnType = returnType.resolve();
                returnInfo.setReturnType(resolvedReturnType.describe());
                returnInfo.setIsPrimitive(typeResolver.isPrimitiveType(resolvedReturnType.describe()));

                if (!Boolean.TRUE.equals(returnInfo.getIsPrimitive())) {
                    List<ApiInfo.Parameter> fields = typeResolver.resolveTypeFields(resolvedReturnType);
                    returnInfo.setFields(fields);
                }
            } catch (Exception e) {
                log.debug("无法解析返回类型: {}", typeName);
            }
        }

        return returnInfo;
    }

    /**
     * 判断是否为RESTful方法
     */
    private boolean isRestfulMethod(MethodDeclaration method) {
        return method.getAnnotations().stream()
                .anyMatch(annotation -> {
                    String annotationName = getSimpleAnnotationName(annotation.getNameAsString());
                    return REST_METHOD_ANNOTATIONS.contains(annotationName);
                });
    }

    /**
     * 构建完整URL
     */
    private String buildFullUrl(String classBaseUrl, String methodUrl) {
        StringBuilder fullUrl = new StringBuilder();

        // 处理类级别URL
        if (classBaseUrl != null && !classBaseUrl.isEmpty()) {
            if (!classBaseUrl.startsWith("/")) {
                fullUrl.append("/");
            }
            fullUrl.append(classBaseUrl);
            if (classBaseUrl.endsWith("/")) {
                fullUrl.setLength(fullUrl.length() - 1);
            }
        }

        // 处理方法级别URL
        if (methodUrl != null && !methodUrl.isEmpty()) {
            if (!methodUrl.startsWith("/")) {
                fullUrl.append("/");
            }
            fullUrl.append(methodUrl);
        }

        // 确保URL以/开头
        String result = fullUrl.toString();
        if (result.isEmpty()) {
            result = "/";
        } else if (!result.startsWith("/")) {
            result = "/" + result;
        }

        return result;
    }

    /**
     * 获取简单类型名称
     */
    private String getSimpleTypeName(String fullTypeName) {
        if (fullTypeName.contains("<")) {
            fullTypeName = fullTypeName.substring(0, fullTypeName.indexOf("<"));
        }

        int lastDot = fullTypeName.lastIndexOf('.');
        return lastDot >= 0 ? fullTypeName.substring(lastDot + 1) : fullTypeName;
    }

    /**
     * 获取简单注解名称
     */
    private String getSimpleAnnotationName(String fullName) {
        int lastDot = fullName.lastIndexOf('.');
        return lastDot >= 0 ? fullName.substring(lastDot + 1) : fullName;
    }
}